﻿using System;
using System.Collections.Generic;
using YArchitech.DataModel;
using YArchitech.LIB;

namespace YArchitech.Plumbing
{
	internal class HYHydrantCal
	{
		public string ShowResults { get; set; }

		public bool Cal(HYSystemCal sys)
		{
			List<HYPipeCal> pipeCals = sys.PipeCals;
			this.fireSystem = sys;
			this.SortOutData();
			if (!this.FireNodeCal())
			{
				return false;
			}
			if (!this.PipePresetCal())
			{
				return false;
			}
			this.BeforDoIt();
			this.ExcuteIt(0);
			this.CalResults();
			return true;
		}

		public void SetNumToPipe(HYPipeCal perpipe, HYPipeCal pipe, ref int nNum)
		{
			if (perpipe == null)
			{
				pipe.nStartNum = nNum - 1;
			}
			else
			{
				pipe.nStartNum = perpipe.nEndNum;
			}
			pipe.nEndNum = nNum;
			nNum++;
			foreach (HYPipeCal pipe2 in pipe.subPipeArray)
			{
				this.SetNumToPipe(pipe, pipe2, ref nNum);
			}
		}

		public bool SortOutData()
		{
			this.dSystemStartElevation = (this.fireSystem.Root as HYPipeCal).ButtonElevation;
			this.listNode.Clear();
			int num = 2;
			this.SetNumToPipe(null, this.fireSystem.Root as HYPipeCal, ref num);
			foreach (HYPipeCal hypipeCal in this.fireSystem.PipeCals)
			{
				if (hypipeCal == this.fireSystem.Root as HYPipeCal)
				{
					HYFireNode hyfireNode = new HYFireNode();
					hyfireNode.nNum = hypipeCal.nStartNum;
					this.listNode.Add(hyfireNode);
				}
				HYFireNode hyfireNode2 = new HYFireNode();
				hyfireNode2.nNum = hypipeCal.nEndNum;
				if (hypipeCal.endFire != null)
				{
					hyfireNode2.bFire = true;
					hypipeCal.endFire.dHigh -= this.dSystemStartElevation;
					hyfireNode2.fireData = hypipeCal.endFire;
				}
				this.listNode.Add(hyfireNode2);
			}
			this.listNode.Sort(new Comparison<HYFireNode>(HYFireNode.CompareByNum));
			return true;
		}

		public bool FireNodeCal()
		{
			HYFireData hyfireData = new HYFireData();
			hyfireData = new HVACUserSetting().GetProtectRadiusSet();
			hyfireData = this.GetFireData(hyfireData);
			double num = -100.0;
			HYFire hyfire = null;
			foreach (HYFire hyfire2 in this.fireSystem.ListFires)
			{
				hyfire2.Flow = hyfireData.DFlow / 1000.0;
				hyfire2.LossPart = hyfireData.DPressure;
				if (hyfire2.LossPart + hyfire2.dHigh > num)
				{
					num = hyfire2.LossPart + hyfire2.dHigh;
					hyfire = hyfire2;
				}
			}
			if (hyfire == null)
			{
				return false;
			}
			hyfire.LossAll = num;
			foreach (HYFireNode hyfireNode in this.listNode)
			{
				if (hyfireNode.fireData == hyfire)
				{
					hyfireNode.dH = num;
				}
			}
			return true;
		}

		public bool PipePresetCal()
		{
			foreach (HYPipeCal hypipeCal in this.fireSystem.PipeCals)
			{
				hypipeCal.Flow = this.PresetFlow(hypipeCal.GetInDN());
				double c = this.calParameter.c;
				double num = this.LostWator(hypipeCal, c);
				hypipeCal.dLostWator = num;
				hypipeCal.dCs = Math.Abs(hypipeCal.Flow / num);
			}
			return true;
		}

		public double PresetFlow(double dNJ)
		{
			double result = 0.0;
			dNJ /= 1000.0;
			if (dNJ == -1.0)
			{
				return result;
			}
			return 628318.53071795858 * dNJ / 4.0 * this.MY_CONST11_8;
		}

		public double LostWator(HYPipeCal pipe, double dc)
		{
			double x = Math.Abs(pipe.Flow);
			double x2 = pipe.GetInDN() / 1000.0;
			double num = 10.7 * Math.Pow(x, 1.852) * pipe.Length;
			double num2 = Math.Pow(dc, 1.852) * Math.Pow(x2, 4.87);
			return num / num2;
		}

		public double GetProtectRadius(double dLd, double dHm)
		{
			double num = 0.8;
			double num2 = 0.71 * dHm;
			return num * dLd + num2;
		}

		public HYFireData GetFireData(HYFireData hyFireData)
		{
			double df = this.GetDf(hyFireData.IDiameter);
			double b = this.GetB(hyFireData.IDiameter);
			double ad = this.GetAd(hyFireData.IType, hyFireData.IMaterial);
			int ilength = hyFireData.ILength;
			if (hyFireData.IKnow == 0)
			{
				double dminFlow = hyFireData.DMinFlow;
				double num = dminFlow * dminFlow / b * 10.0;
				double num2 = ad * (double)ilength * dminFlow * dminFlow * 10.0;
				hyFireData.DPressure = (num + num2 + 20.0) / 10.0;
				hyFireData.DMinLength = num / (1.2 * (10.0 + df * num));
				double num3 = Math.Ceiling(Convert.ToDouble(hyFireData.DMinLength));
				double num4 = 1.19 + 80.0 * Math.Pow(0.01 * num3, 4.0);
				double num5 = num4 * num3 / (1.0 - df * num4 * num3);
				hyFireData.DFlow = Math.Sqrt(b * num5);
			}
			else
			{
				double dminLength = hyFireData.DMinLength;
				double num6 = 1.19 + 80.0 * Math.Pow(0.01 * dminLength, 4.0);
				double num7 = num6 * dminLength / (1.0 - df * num6 * dminLength);
				double num8 = Math.Sqrt(b * num7);
				hyFireData.DFlow = num8;
				double num9 = ad * (double)ilength * num8 * num8;
				hyFireData.DPressure = num7 + num9 + 2.0;
			}
			return hyFireData;
		}

		private double GetDf(int iDiameter)
		{
			return new Dictionary<int, double>
			{
				{
					0,
					0.0165
				},
				{
					1,
					0.0124
				},
				{
					2,
					0.0097
				}
			}[iDiameter];
		}

		private double GetB(int iDiameter)
		{
			return new Dictionary<int, double>
			{
				{
					0,
					0.346
				},
				{
					1,
					0.793
				},
				{
					2,
					1.577
				}
			}[iDiameter];
		}

		private double GetAd(int iType, int iMaterial)
		{
			Dictionary<string, double> dictionary = new Dictionary<string, double>();
			dictionary.Add("50A", 0.01501);
			dictionary.Add("50B", 0.00677);
			dictionary.Add("65A", 0.0043);
			dictionary.Add("65B", 0.00172);
			string key;
			if (iType == 0)
			{
				key = ((iMaterial == 2) ? "50B" : "50A");
			}
			else
			{
				key = ((iMaterial == 2) ? "65B" : "65A");
			}
			return dictionary[key];
		}

		private bool BeforDoIt()
		{
			int count = this.listNode.Count;
			int num = -1;
			HYHydrantMatrix hyhydrantMatrix = new HYHydrantMatrix(count);
			int num2 = 0;
			foreach (HYFireNode hyfireNode in this.listNode)
			{
				HYHydrantGroup hyhydrantGroup = new HYHydrantGroup();
				hyhydrantGroup.SetSize(count + 1);
				if (hyfireNode.dH > 0.0001)
				{
					num = num2;
				}
				int num3 = this.IsNodeInt(hyfireNode.nNum);
				if (hyfireNode.fireData != null)
				{
					hyhydrantGroup.SetAt(count, 0.0 - hyfireNode.fireData.Flow);
				}
				foreach (HYPipeCal hypipeCal in this.fireSystem.PipeCals)
				{
					int num4 = this.IsNodeInt(hypipeCal.nStartNum);
					int num5 = this.IsNodeInt(hypipeCal.nEndNum);
					if (num4 == num3)
					{
						hyhydrantGroup.SetAt(num4, hyhydrantGroup.GetAt(num4) + hypipeCal.dCs);
						hyhydrantGroup.SetAt(num5, hyhydrantGroup.GetAt(num5) - hypipeCal.dCs);
					}
					if (num5 == num3)
					{
						hyhydrantGroup.SetAt(num4, hyhydrantGroup.GetAt(num4) - hypipeCal.dCs);
						hyhydrantGroup.SetAt(num5, hyhydrantGroup.GetAt(num5) + hypipeCal.dCs);
					}
				}
				hyhydrantMatrix.SetGroupItem(num2, hyhydrantGroup);
				num2++;
			}
			int i = this.IsNodeInt((this.fireSystem.Root as HYPipeCal).nStartNum);
			HYHydrantGroup hyhydrantGroup2 = new HYHydrantGroup();
			hyhydrantGroup2.SetSize(count + 1);
			hyhydrantGroup2.SetAt(num, 1.0);
			if (num != -1)
			{
				hyhydrantGroup2.SetAt(count, this.listNode[num].dH);
			}
			hyhydrantMatrix.ModifyGroupItem(i, hyhydrantGroup2);
			if (!hyhydrantMatrix.Calculate())
			{
				return false;
			}
			foreach (HYPipeCal hypipeCal2 in this.fireSystem.PipeCals)
			{
				int num6 = this.IsNodeInt(hypipeCal2.nStartNum);
				int num7 = this.IsNodeInt(hypipeCal2.nEndNum);
				double num8 = 0.0;
				double num9 = 0.0;
				if (num6 != -1 && num6 < hyhydrantMatrix.m_GRezult.Count)
				{
					num8 = hyhydrantMatrix.m_GRezult[num6];
				}
				if (num7 != -1 && num7 < hyhydrantMatrix.m_GRezult.Count)
				{
					num9 = hyhydrantMatrix.m_GRezult[num7];
				}
				hypipeCal2.FlowN = (num8 - num9) * hypipeCal2.dCs;
			}
			return true;
		}

		public int IsNodeInt(int nNode)
		{
			for (int i = 0; i < this.listNode.Count; i++)
			{
				if (this.listNode[i].nNum == nNode)
				{
					return i;
				}
			}
			return -1;
		}

		public bool ExcuteIt(int iCS)
		{
			int count = this.listNode.Count;
			int num = -1;
			HYHydrantMatrix hyhydrantMatrix = new HYHydrantMatrix(count);
			int i = 0;
			foreach (HYFireNode hyfireNode in this.listNode)
			{
				HYHydrantGroup hyhydrantGroup = new HYHydrantGroup();
				hyhydrantGroup.SetSize(count + 1);
				if (hyfireNode.dH > 0.0001)
				{
					num = i;
				}
				int num2 = this.IsNodeInt(hyfireNode.nNum);
				if (hyfireNode.fireData != null)
				{
					hyhydrantGroup.SetAt(count, 0.0 - hyfireNode.fireData.Flow);
				}
				foreach (HYPipeCal hypipeCal in this.fireSystem.PipeCals)
				{
					int num3 = this.IsNodeInt(hypipeCal.nStartNum);
					int num4 = this.IsNodeInt(hypipeCal.nEndNum);
					if (num3 == num2)
					{
						hyhydrantGroup.SetAt(num3, hyhydrantGroup.GetAt(num3) + hypipeCal.dCs);
						hyhydrantGroup.SetAt(num4, hyhydrantGroup.GetAt(num4) - hypipeCal.dCs);
					}
					if (num4 == num2)
					{
						hyhydrantGroup.SetAt(num3, hyhydrantGroup.GetAt(num3) - hypipeCal.dCs);
						hyhydrantGroup.SetAt(num4, hyhydrantGroup.GetAt(num4) + hypipeCal.dCs);
					}
				}
				hyhydrantMatrix.SetGroupItem(i, hyhydrantGroup);
				i++;
			}
			int i2 = this.IsNodeInt((this.fireSystem.Root as HYPipeCal).nStartNum);
			HYHydrantGroup hyhydrantGroup2 = new HYHydrantGroup();
			hyhydrantGroup2.SetSize(count + 1);
			hyhydrantGroup2.SetAt(num, 1.0);
			if (num != -1)
			{
				hyhydrantGroup2.SetAt(count, this.listNode[num].dH);
			}
			hyhydrantMatrix.ModifyGroupItem(i2, hyhydrantGroup2);
			if (!hyhydrantMatrix.Calculate())
			{
				return false;
			}
			count = hyhydrantMatrix.m_GRezult.Count;
			for (i = 0; i < count; i++)
			{
				this.listNode[i].dH = hyhydrantMatrix.m_GRezult[i];
			}
			if (iCS++ < 50)
			{
				return this.GetMaxQ(num, iCS);
			}
			this.bExcutfalse = true;
			return true;
		}

		public bool GetMaxQ(int iHave, int iCS)
		{
			bool flag = true;
			foreach (HYPipeCal hypipeCal in this.fireSystem.PipeCals)
			{
				int num = this.IsNodeInt(hypipeCal.nStartNum);
				int num2 = this.IsNodeInt(hypipeCal.nEndNum);
				double num3 = 0.0;
				double num4 = 0.0;
				if (num != -1 && num < this.listNode.Count)
				{
					num3 = this.listNode[num].dH;
				}
				if (num2 != -1 && num2 < this.listNode.Count)
				{
					num4 = this.listNode[num2].dH;
				}
				hypipeCal.FlowN = (num3 - num4) * hypipeCal.dCs;
				if (Math.Abs(Math.Abs(hypipeCal.FlowN) - Math.Abs(hypipeCal.Flow)) > 1E-05)
				{
					flag = false;
				}
			}
			if (flag)
			{
				return true;
			}
			int count = this.listNode.Count;
			for (int i = 0; i < count; i++)
			{
				if (i != iHave)
				{
					this.listNode[i].dH = 0.0;
				}
			}
			this.UpdateStruct();
			return this.ExcuteIt(iCS);
		}

		public void UpdateStruct()
		{
			double c = this.calParameter.c;
			foreach (HYPipeCal hypipeCal in this.fireSystem.PipeCals)
			{
				double flowN = hypipeCal.FlowN;
				hypipeCal.Flow = flowN;
				double num = this.LostWator(hypipeCal, c);
				hypipeCal.dLostWator = num;
				hypipeCal.dCs = Math.Abs(hypipeCal.Flow / num);
			}
		}

		public void DisPressCal()
		{
		}

		private void CalResults()
		{
			List<HYPipeCal> list = new List<HYPipeCal>();
			foreach (HYPipeCal hypipeCal in this.fireSystem.PipeCals)
			{
				if (hypipeCal.endFire != null)
				{
					list.Add(hypipeCal);
				}
			}
			double num = 0.0;
			foreach (HYPipeCal hypipeCal2 in list)
			{
				double pressFromEnd = this.GetPressFromEnd(hypipeCal2, hypipeCal2.endFire.dHigh + hypipeCal2.endFire.LossPart);
				if (num < pressFromEnd)
				{
					num = pressFromEnd;
					HYFire endFire = hypipeCal2.endFire;
				}
			}
			foreach (HYPipeCal hypipeCal3 in this.fireSystem.PipeCals)
			{
				hypipeCal3.Flow *= 1000.0;
				double inDN = hypipeCal3.GetInDN();
				double num2 = Math.PI * inDN * inDN / 4.0;
				num2 /= 1000000.0;
				hypipeCal3.Velocity = Math.Abs(hypipeCal3.Flow / 1000.0 / num2);
			}
			num = Math.Round(num, 1);
			this.ShowResults = "计算完成，系统要求入口压力（米水柱）：" + num.ToString();
			this.fireSystem.ShowResults = this.ShowResults;
		}

		private double GetPressFromEnd(HYPipeCal pipe, double dPress)
		{
			if (pipe == null)
			{
				return dPress;
			}
			dPress += pipe.dLostWator;
			if (pipe.perviousPipe == null)
			{
				return dPress;
			}
			return this.GetPressFromEnd(pipe.perviousPipe, dPress);
		}

		private HYSystemCal fireSystem;

		private List<HYFireNode> listNode = new List<HYFireNode>();

		public HYCalParameter calParameter = new HYCalParameter();

		public const int JSCS = 50;

		public bool bExcutfalse;

		private double dSystemStartElevation;

		public double MY_CONST11_8 = 1.145E-06;
	}
}
